package com.zhuxulin.android.net;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Dialog;
import android.content.Context;
import android.net.http.AndroidHttpClient;
import android.util.Log;

import com.google.gson.Gson;
import com.zhuxulin.android.utils.DateFormatUtil;
import com.zhuxulin.android.utils.LogUtil;

public class HttpClient {
	private static final String TAG = HttpClient.class.getSimpleName();
	private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

	private static HttpClient instance = null;

	private Context context = null;
	private HttpContext httpContext = null;
	private CookieStore cookieStore = null;
	private HttpParams httpParams = null;
	private Dialog dialog = null;
	private IResult iResult = null;

	/** 获取默认的请求客户端 */
	public static HttpClient getInstance() {
		return getInstance(null, null);
	}

	/** 获取带回调接口的客户端 */
	public static HttpClient getInstance(IResult iResult) {
		return getInstance(null, null, iResult);
	}

	/** 获取带加载框的客户端 */
	public static HttpClient getInstance(Context context, Dialog dialog) {
		return getInstance(context, dialog, null);
	}

	/**
	 * 获取带加载框和回调接口的客户端，context 和 dialog 必须同时为空或者同时不为空
	 * 
	 * @param context
	 * @param dialog
	 * @param iResult
	 * @return
	 */
	public static HttpClient getInstance(Context context, Dialog dialog, IResult iResult) {
		if (!check(context, dialog)) {
			throw new RuntimeException("context 和 dialog 必须同时为空或者同时不为空!");
		}
		if (instance == null) {
			instance = new HttpClient();
		}
		instance.context = context;
		instance.dialog = dialog;
		instance.iResult = iResult;
		return instance;
	}

	private static boolean check(Context c, Dialog d) {
		if (null == c) {
			return null == d;
		}
		return d != null;
	}

	private HttpClient() {
		httpContext = new BasicHttpContext();
		cookieStore = new BasicCookieStore();
		httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
		httpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(httpParams, 10000);
		HttpConnectionParams.setSoTimeout(httpParams, 10000);
	}

	/**
	 * 重置网络连接，清空Cookie
	 */
	public void reset() {
		cookieStore.clear();
	}

	/**
	 * 执行相应的网络请求
	 * 
	 * @param request
	 *            请求对象
	 * @param dataType
	 *            结果集中dataSet的解释类型，为null时忽略该数据
	 * @return 请求结果
	 */
	public <T> Response<T> execute(Request request, Class<T> dataType) {
		Response<T> response = null;
		HttpUriRequest req = null;
		req = getHttpUriRequest(request);
		req.setParams(httpParams);

		AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
		try {
			LogUtil.i(TAG, request.toString());
			HttpResponse resp = client.execute(req, httpContext);
			if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				StringBuffer content = new StringBuffer();
				InputStream in = resp.getEntity().getContent();
				byte[] buf = new byte[1024];
				int count = 0;
				while ((count = in.read(buf, 0, buf.length)) > 0) {
					content.append(new String(buf, 0, count, "utf-8"));
				}
				in.close();
				// 有待优化
				// new Gson().fromJson(content.toString(), dataType);
				LogUtil.i(TAG, content.toString());
				if (iResult != null) {
					iResult.onResult(content.toString());
				}
			} else {
				response = new Response<T>();
				response.code = -resp.getStatusLine().getStatusCode();
				response.message = request.toString();
			}
		} catch (IOException e) {
			response = new Response<T>();
			response.code = Response.CODE_NETWORK_ERROR;
			response.message = e.getMessage();
			LogUtil.i(TAG, "IOException\n" + e.getMessage());
			return response;
		} catch (IllegalArgumentException e) {
			response = new Response<T>();
			response.code = Response.CODE_SERVER_ADDR_ERROR;
			response.message = request.getURL();
			LogUtil.i(TAG, "IllegalArgumentException\n" + e.getMessage());
			return response;
		} finally {
			LogUtil.i(TAG, "finally");
			client.close();
		}
		return response;
	}

	private HttpUriRequest getHttpUriRequest(Request r) {
		HttpUriRequest req = null;
		switch (r.getMethod()) {
		case GET:
			req = new HttpGet(r.getURL());
			break;
		case POST:
			req = new HttpPost(r.getURI());
			((HttpPost) req).setEntity(r.getEntity());
			break;
		case PUT:
			req = new HttpPut(r.getURI());
			((HttpPut) req).setEntity(r.getEntity());
			break;
		case DELETE:
			req = new HttpDelete(r.getURL());
			break;
		}
		return req;
	}
}
